﻿#include "showplatform.h"
#include "ui_showplatform.h"
#include <iostream>

ShowPlatform::ShowPlatform(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::ShowPlatform)
{
    ui->setupUi(this);
    this->setFixedSize(QSize(WIDTH, HEIGHT));
    Init();
    isopen = loadfile(existingDoc, BANK_FILE_PATH);
    P_ins = ParsexmlIns::getInstance();
    _addform = new AddPlatform();
    connect(_addform, &AddPlatform::sendAddSignal, [this](AddEv *addev){
        addAllchildnodes(addev);
    });
    connect(_addform, &AddPlatform::sendModSignal, [this](AddEv *addev, map<int, map<QString, QStringList>> Data_Map){
        ModAllchildnodes(addev, Data_Map);
    });
    connect(_addform, &AddPlatform::sendRemoveSignal, [this](AddEv *addev, map<int, map<QString, QStringList>> Data_Map){
        RemoveAllchildnodes(addev, Data_Map);
    });
    connect(_addform, &AddPlatform::sendParsefinished, [this](){
        auto fu = ThreadPool::Instance().commit([this](){
            generateAllXml();
        });
        fu.get();
    });
}
//        auto xmlpath = P_ins->getxmlpath();//jc
//        openxmlFile(xmlpath, "_alp_.xml", );//jc
//        P_ins->setxmlpath(xmlpath);//jc
//        auto xmlpath = P_ins->getxmlpath();
//        QMessageBox::information(this, "提示", QString("解析完成！alp路径：%1").arg(xmlpath));

ShowPlatform::~ShowPlatform()
{
    T_map.clear();
    Root_map.clear();
    delete ui;
}

void ShowPlatform::Init()
{
    ui->filenameEdit->setReadOnly(true);
    ui->textEdit->setReadOnly(true);
}

bool ShowPlatform::loadfile(pugi::xml_document &Doc, const char *filename)
{
    return Doc.load_file(filename);
}

bool ShowPlatform::savefile(pugi::xml_document &Doc, const char *filename)
{
    return Doc.save_file(filename);
}

pugi::xml_node ShowPlatform::findtargetNode(const char *targetNodeName)
{
    pugi::xml_node targetnode = existingDoc.select_node(targetNodeName).node();
    return targetnode;
}

void ShowPlatform::addAllchildnodes(/*const QDomNode &node, *//*QVector<int>checkVec,*/ AddEv *addev/*, QMap<QString, QString> &Data_Map*/)
{
    if(addev->getId() == addType::EVENT){
        addEvent(addType::EVENT);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }

    if(addev->getId() == addType::Parm){
        addParm(addType::Parm);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }

    if(addev->getId() == addType::Agent){
        addAgent(addType::Agent);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }

}

void ShowPlatform::ModAllchildnodes(AddEv *addev, map<int, map<QString, QStringList>> &Data_Map)
{
    if(addev->getId() == addType::EVENT){
        modEvent(addType::EVENT, Data_Map);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }

    if(addev->getId() == addType::Parm){
        modParm(addType::Parm, Data_Map);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }

    if(addev->getId() == addType::Agent){
        modAgent(addType::Agent, Data_Map);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }
}

//待修改移除事件
void ShowPlatform::RemoveAllchildnodes(AddEv *addev, map<int, map<QString, QStringList>> &Data_Map)
{
    if(addev->getId() == addType::EVENT){
        k ++;
        removeEvent(Data_Map);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }

    if(addev->getId() == addType::Parm){
        k ++;
        removeParm(Data_Map);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }

    if(addev->getId() == addType::Agent){
        k ++;
        removeAgent(Data_Map);
        qDebug() << "ShowPlatform::parseXml ---> Produce Record = " << k;
    }
}

void ShowPlatform::on_openBtn_clicked()
{
    auto xmlpath = QFileDialog::getOpenFileName(this, "打开文件", "/", "XML files (*.xml)");
    if(!xmlpath.isEmpty()){
        ui->filenameEdit->setText(xmlpath);
        openxmlFile(xmlpath.toUtf8().constData(), xmlcontent);
        getgeneratealppath(xmlpath);
        P_ins->setxmlpath(xmlpath);
        P_ins->setxmlcontent(xmlcontent);
        ui->textEdit->setText(xmlcontent);
        isopenxml = true;
    }else{
        return;
    }
}

void ShowPlatform::on_AddBtn_clicked()
{
//    if(isopenxml){
        _addform->show();
        auto res = ThreadPool::Instance().commit([this](){
            P_ins->parseXml();
        });
        res.get();
        _addform->fillJsonsToPlainText();
//        std::this_thread::sleep_for(std::chrono::milliseconds(500));
//    }
}

void ShowPlatform::addInterface(int Eventtype)
{
    k ++;
    _name = P_ins->getname();
    //    qDebug() << _name;
    if(!m.count(_name)){
        InitmMap();
    }
    if(!InitTMap(Eventtype)){
        return;
    }

}

void ShowPlatform::addEvent(int Eventtype)
{
    addInterface(Eventtype);
    qDebug() << "ShowPlatform::addEvent --> add event success.";
}

void ShowPlatform::addParm(int Eventtype)
{
    addInterface(Eventtype);
    qDebug() << "ShowPlatform::addParm --> add parm success.";
}

void ShowPlatform::addAgent(int Eventtype)
{
    addInterface(Eventtype);
    qDebug() << "ShowPlatform::addAgent --> add agent success.";
}

void ShowPlatform::removeEvent(map<int, map<QString, QStringList>> &Data_Map)
{
    qDebug() << "ShowPlatform::removeEvent --> remove event success.";
}

void ShowPlatform::removeParm(map<int, map<QString, QStringList>> &Data_Map)
{
    qDebug() << "ShowPlatform::removeParm --> remove parm success.";
}

void ShowPlatform::removeAgent(map<int, map<QString, QStringList>> &Data_Map)
{
    qDebug() << "ShowPlatform::removeAgent --> remove agent success.";
}

void ShowPlatform::modInterface(int Eventtype, map<int, map<QString, QStringList>> &Data_Map)
{
    k ++;
    _name = P_ins->getname();
    //    qDebug() << _name;
    auto iter = T_map.find(Eventtype);
    if(iter == T_map.end()){
        qDebug() << "ShowPlatform::modInterface ---> Please add event ! Because T_map's Eventtype(key) is null";
        return;
    }

    for(auto DmapIt = Data_Map.begin(); DmapIt != Data_Map.end(); ++DmapIt){
        auto page = DmapIt->first;
        auto Data_Map = DmapIt->second;
        auto tm = iter->second;
        auto it = Data_Map.find(_name);

        auto t = tm.find(_name);
        if(t == tm.end()){
            qDebug() << "ShowPlatform::modInterface ---> Please check T_map ! Because T_map's key's name is null";
            return;
        }else{
            auto xmlcontent = t->second;
            modifyXmlNodeData(page, xmlcontent, Data_Map);
            T_map[Eventtype][_name] = xmlcontent;
            //            for(auto &str : T_map[Eventtype][_name]){
            //                qDebug() << str;
            //            }
        }

    }
}

void ShowPlatform::modEvent(int Eventtype, map<int, map<QString, QStringList>> &Data_Map)
{
    modInterface(Eventtype, Data_Map);
    qDebug() << "ShowPlatform::modEvent --> mod event success.";
}

void ShowPlatform::modParm(int Eventtype, map<int, map<QString, QStringList>> &Data_Map)
{
    modInterface(Eventtype, Data_Map);
    qDebug() << "ShowPlatform::modParm --> mod parm success.";
}

void ShowPlatform::modAgent(int Eventtype, map<int, map<QString, QStringList>> &Data_Map)
{
    modInterface(Eventtype, Data_Map);
    qDebug() << "ShowPlatform::modAgent --> mod agent success.";
}

void ShowPlatform::generateAllXml()
{
    {
        if(m.empty()){
            qDebug() << "m_map is empty !";
            return;
        }
        if(T_map.empty()){
            qDebug() << "T_map is empty !";
            return;
        }
        {
            std::lock_guard<std::mutex> lk(mtx);
            //            for(auto iter = T_map.begin(); iter != T_map.end(); ++iter){
            //                auto key = iter->first;
            //                auto value = iter->second;
            //                qDebug() << key;
            //                for(auto it = value.begin(); it != value.end(); ++it){
            //                    auto key = it->first;
            //                    auto value = it->second;
            //                    qDebug() << key << " : " << value;
            //                }
            //            }
            this->Res_Map = P_ins->getRes_Map();
            this->Root_map = P_ins->getRoot_map();
            for(auto iter = Res_Map.begin(); iter != Res_Map.end(); ++iter){
                auto key = iter->first;
//                qDebug() << key;
                if(key == addType::EVENT){
                    auto parentNode = findtargetNode("//ActiveObjectClass");
                    addNodeToNode(parentNode, QString("Events"));
                }
                auto add_map = T_map[key];
                auto value = iter->second;
                for(auto &name : value){
                    auto contents = add_map[name];
                    auto root = Root_map[name];
                    //                    qDebug() << contents.size();
                    for(int i = 0; i < contents.size(); ++i){
                        appendXmlToNode(root[i].toUtf8().constData(), contents[i]);
                    }
                }
            }

            qDebug() << "ShowPlatform::generateAllXml ---> generate xmls success.";

            //                        for(auto iter = Root_map.begin(); iter != Root_map.end(); ++iter){
            //                            auto key = iter->first;
            //                            auto value = iter->second;
            //                            qDebug() << key << ":" << value;
            //                        }

            //                        for(auto iter = TemPath_Map.begin(); iter != TemPath_Map.end(); ++iter){
            //                            auto key = iter->first;
            //                            auto value = iter->second;
            //                            qDebug() << key << ":" << value;
            //                        }
        }
    }
}

bool ShowPlatform::InitTMap(int EventType)
{
    if(!T_map.count(EventType)){
        map<QString, vector<QString>> tm;
        tm[_name] = m[_name];
        T_map[EventType] = tm;
    }
    else{
        auto tm = T_map[EventType];
        if(!tm.count(_name)){
            tm.insert(std::pair<QString, vector<QString>>(_name, m[_name]));
            T_map[EventType] = tm;
        }else{
            qDebug() << "ShowPlatform::InitTMap ---> T_map failed.";
            return false;
        }
    }
    return true;
}

void ShowPlatform::InitmMap()
{
    TemPath_Map = P_ins->getTemPath_Map();
    filepath = TemPath_Map[_name];

    std::thread t([this](){
        v.clear();
        openneedtemplateXmls(filepath, v);
    });
    t.join();
    {
        std::lock_guard<std::mutex> lk(mtx);
        m[_name] = v;
    }

    //    m.insert(pair<int, vector<QString>>(EventType, v));
}

void ShowPlatform::openneedtemplateXmls(QString filepath, vector<QString> &v)
{
    QDir dir(filepath);
    if (!dir.exists()) {
        return;
    }
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    QFileInfoList fileList = dir.entryInfoList();
    for (const QFileInfo& fileInfo : fileList) {
        QString filePath = fileInfo.absoluteFilePath();
        QFile file(filePath);
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QString content = file.readAll();
            v.push_back(content);
            file.close();
        } else {
            return;
        }
    }
    return;
}

void ShowPlatform::getgeneratealppath(QString &xmlpath)
{
    int lastIndex = xmlpath.lastIndexOf("/");
    if(lastIndex != -1){
        xmlpath = xmlpath.left(lastIndex + 1);
    }
}

bool ShowPlatform::appendXmlToNode(/*const char *existingXmlPath, *//*const char *templateXmlPath,*/const char *targetNodeName, QString &content)
{
    if(isopen){
        pugi::xml_node targetNode;
        if(!(targetNode = findtargetNode(targetNodeName))){
            qDebug() << "ShowPlatform::appendXmlToNode ---> targetNode find failed.";
            return false;
        }
        addXmlToNode(targetNode, content);
        if(!savefile(existingDoc, BANK_FILE_PATH)){
            return false;
        }
    }
    return true;
}

void ShowPlatform::addXmlToNode(pugi::xml_node &parentNode, QString &xmlContent)
{
    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_string(xmlContent.toUtf8().constData());

    if (result) {
        for (pugi::xml_node child : doc.children()) {
            parentNode.append_copy(child);
        }
    } else {
        std::cerr << "Failed to parse XML: " << result.description() << std::endl;
        return;
    }
}

void ShowPlatform::addNodeToNode(pugi::xml_node &parentNode, const QString &targetNodename)
{
    if(!parentNode){
        qDebug() << "ShowPlatform::addNodeToNode ---> parentNode find failed.";
        return;
    }
    auto targetNode = parentNode.append_child(targetNodename.toUtf8().constData());
    if(!targetNode){
        qDebug() << "ShowPlatform::addNodeToNode ---> add node to Node failed.";
        return;
    }
}

bool ShowPlatform::modifyXmlNodeData(int &page, vector<QString> &xmlcontent, map<QString, QStringList> &Data_Map)
{
    for(auto it = Data_Map.begin(); it != Data_Map.end(); ++it){
        auto key = it->first;
        auto value = it->second;
        auto res = findWitchtemplatexml(page, key, value, xmlcontent);
        if(-1 == res){
            qDebug() << "ShowPlatform::modifyXmlNodeData ---> xml node not find !";
            return false;
        }
    }
    return true;
}

void ShowPlatform::modifyXmlData(int ans, pugi::xml_node &targetNode, QStringList &value, vector<QString> &xmlcontent)
{
    if(value.size() == 1){
        auto text = value.front();
        if(!text.isEmpty()){
            targetNode.text().set(text.toUtf8().constData());
        }
    }

    if(value.size() == 2){
        auto attrname = value.front();
        auto attrvalue = value.back();
        pugi::xml_attribute attr = targetNode.attribute(attrname.toUtf8().constData());
        if (attr) {
            attr.set_value(attrvalue.toUtf8().constData());
        } else {
            targetNode.append_attribute(attrname.toUtf8().constData())
                .set_value(attrvalue.toUtf8().constData());
        }
    }
}

int ShowPlatform::findWitchtemplatexml(int &page, QString &key, QStringList &value, vector<QString> &xmlcontent)
{
    auto xml = xmlcontent[page];
    //        qDebug() << xml;
    pugi::xml_parse_result result = xml_doc.load_string(xml.toUtf8().constData());
    if(result){
        modifyRecursive(page, xml_doc, key, value, xmlcontent);
        std::stringstream ss;
        xml_doc.save(ss);
        xmlcontent[page] = QString::fromUtf8(ss.str().c_str());
        return 0;
    }
    return -1;
}

void ShowPlatform::modifyRecursive(int i, pugi::xml_node node, QString &key, QStringList &value, vector<QString> &xmlcontent)
{
    for (pugi::xml_node child : node.children()) {
        if (QString::fromUtf8(child.name()) == key) {
            targetNode = child;
            modifyXmlData(i, targetNode, value, xmlcontent);
            return;
        }
        else{
            QStringList strList = key.split("/");
            std::vector<QString> tm;
            for(auto &str : strList){
                tm.push_back(str);
            }
            modifyRecursive(i, tm, xml_doc, value, xmlcontent);
        }
        modifyRecursive(i, child, key, value, xmlcontent);
    }
}

void ShowPlatform::modifyRecursive(int i, std::vector<QString> &RootVec, pugi::xml_node node, QStringList &value, vector<QString> &xmlcontent)
{
    for (pugi::xml_node child : node.children()) {
        if (ismodfiyNodeData(RootVec, child)) {
            targetNode = child;
            modifyXmlData(i, targetNode, value, xmlcontent);
            return;
        }
        modifyRecursive(i, RootVec, child, value, xmlcontent);
    }
}

bool ShowPlatform::ismodfiyNodeData(std::vector<QString> &RootVec, pugi::xml_node node)
{
    std::vector<QString> tm = RootVec;
    while(tm.size() > 0){
        if(tm.back() != QString::fromUtf8(node.name())){
            return false;
        }
        else{
            tm.pop_back();
            node = node.parent();
        }
    }
    return true;
}




